unit FormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, cxBitBtn, ToolWin, ActnMan, ActnCtrls, ActnMenus, ActnList,
  Menus, Buttons, ComCtrls, JvExComCtrls, JvDateTimePicker, JvExStdCtrls,
  JvListBox, Mask, JvExMask, JvSpin, ExtCtrls, JvExControls,
  JvSegmentedLEDDisplay, TextFade;

type
  TFrmMain = class(TForm)
    mmMain: TMainMenu;
    actlstMain: TActionList;
    actAdd: TAction;
    actRemove: TAction;
    actSave: TAction;
    actLoad: TAction;
    File1: TMenuItem;
    actNew: TAction;
    actNew1: TMenuItem;
    actSave1: TMenuItem;
    actLoad1: TMenuItem;
    Items1: TMenuItem;
    actAdd1: TMenuItem;
    actRemove1: TMenuItem;
    N1: TMenuItem;
    actClose: TAction;
    Close1: TMenuItem;
    actStart: TAction;
    actStop: TAction;
    btnStart: TBitBtn;
    btnAdd: TBitBtn;
    btnRemove: TBitBtn;
    btnStop: TBitBtn;
    btnClose: TBitBtn;
    lstTimes: TJvListBox;
    tmrMain: TTimer;
    labTimer: TJvSegmentedLEDDisplay;
    dtpTime: TJvDateTimePicker;
    TextFader: TTextFader;
    N2: TMenuItem;
    actFile: TAction;
    actItems: TAction;
    procedure actCloseExecute(Sender: TObject);
    procedure actAddExecute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure actRemoveExecute(Sender: TObject);
    procedure actRemoveUpdate(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
    procedure actLoadExecute(Sender: TObject);
    procedure actNewExecute(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure lstTimesClick(Sender: TObject);
    procedure edtTimeChange(Sender: TObject);
    procedure actStartExecute(Sender: TObject);
    procedure actStopExecute(Sender: TObject);
    procedure actAddUpdate(Sender: TObject);
    procedure actStartUpdate(Sender: TObject);
    procedure actStopUpdate(Sender: TObject);
    procedure actNewUpdate(Sender: TObject);
    procedure actSaveUpdate(Sender: TObject);
    procedure actLoadUpdate(Sender: TObject);
    procedure tmrMainTimer(Sender: TObject);
    procedure actCloseUpdate(Sender: TObject);
    procedure lstTimesDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lstTimesMeasureItem(Control: TWinControl; Index: Integer;
      var Height: Integer);
    procedure actFileExecute(Sender: TObject);
    procedure actItemsExecute(Sender: TObject);
  private
    { Private declarations }
    FModified: Boolean;
    FRemainingTime: Integer;
    function SaveToFile: Boolean;
    function CheckModified: Boolean;
    procedure SetRemainingTime(const Value: Integer);
  public
    { Public declarations }
    function SecToText(Value: Integer): string;

    property Modified: Boolean read FModified write FModified;
    property RemainingTime: Integer read FRemainingTime write SetRemainingTime;
  end;

var
  FrmMain: TFrmMain;

implementation
uses
  JvGnugettext, MMSystem, cxGraphics;

{$R *.dfm}

procedure TFrmMain.actAddExecute(Sender: TObject);
begin
  lstTimes.Items.AddObject('60', Pointer(60));
  lstTimes.ItemIndex := lstTimes.Items.Count -1;
  lstTimesClick(lstTimes);
  Modified := true;
end;

procedure TFrmMain.actAddUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := not tmrMain.Enabled;
end;

procedure TFrmMain.actCloseExecute(Sender: TObject);
begin
  Close;
end;

procedure TFrmMain.actCloseUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := not tmrMain.Enabled;
end;

procedure TFrmMain.actFileExecute(Sender: TObject);
begin
  {Nothing}
end;

procedure TFrmMain.actItemsExecute(Sender: TObject);
begin
  {Nothing}
end;

procedure TFrmMain.actLoadExecute(Sender: TObject);
begin
  if CheckModified then
    with TOpenDialog.Create(Self) do
    try
      DefaultExt := '.tick';
      Filter := _('Tick tick files (*.tick)|*tick|Any file|*.*');
      if Execute then
      try
        lstTimes.Items.LoadFromFile(FileName);
        Modified := false;
      except
        MessageDlg(Format(_('Can''not load the filename %s'), [FileName]), mtError, [mbOK], 0);
      end;
    finally
      Free;
    end;
end;

procedure TFrmMain.actLoadUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := not tmrMain.Enabled;
end;

procedure TFrmMain.actNewExecute(Sender: TObject);
begin
  if CheckModified then
  begin
    lstTimes.Items.Clear;
    Modified := False;
  end;
end;

procedure TFrmMain.actNewUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := not tmrMain.Enabled;
end;

procedure TFrmMain.actRemoveExecute(Sender: TObject);
begin
  lstTimes.Items.Delete(lstTimes.ItemIndex);
  Modified := true;
end;

procedure TFrmMain.actRemoveUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := (lstTimes.ItemIndex >= 0) and (not tmrMain.Enabled);
end;

procedure TFrmMain.actSaveExecute(Sender: TObject);
begin
  SaveToFile;
end;

procedure TFrmMain.actSaveUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := not tmrMain.Enabled;
end;

procedure TFrmMain.actStartExecute(Sender: TObject);
begin
  PlaySound('metronome', hInstance, SND_RESOURCE or SND_ASYNC or SND_LOOP);
  lstTimes.ItemIndex := 0;
  tmrMain.Enabled := true;

  RemainingTime := StrToInt(lstTimes.Items[0]);
end;

procedure TFrmMain.actStartUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := (not tmrMain.Enabled) and (lstTimes.Items.Count > 0);
  lstTimes.Enabled := (not tmrMain.Enabled);
  dtpTime.Enabled := (not tmrMain.Enabled);
end;

procedure TFrmMain.actStopExecute(Sender: TObject);
begin
  tmrMain.Enabled := false;
  labTimer.Text := '';
  PlaySound('stop', hInstance, SND_RESOURCE or SND_ASYNC);
  lstTimesClick(lstTimes);
end;

procedure TFrmMain.actStopUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := tmrMain.Enabled;
end;

function TFrmMain.CheckModified: Boolean;
begin
  Result := not Modified;
  if Modified then
    case MessageDlg(_('Save changes?'), mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
      mrCancel:
        result := False;
      mrYes:
        Result := SaveToFile;
      mrNo:
        result := True;
    end;
end;

procedure TFrmMain.edtTimeChange(Sender: TObject);
var
  H, M, S, SSec: Word;
begin
  DecodeTime(dtpTime.Time, H, M, S, SSec);
  if lstTimes.ItemIndex >= 0 then
  begin
    lstTimes.Items[lstTimes.ItemIndex] := IntToStr(M *60 +S);
    lstTimes.Items.Objects[lstTimes.ItemIndex] := Pointer(M *60 +S);
  end;
end;

procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := (not tmrMain.Enabled) and CheckModified;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  Modified := False;
  TranslateComponent(Self, '');

  TextFader.Active := true;
end;

procedure TFrmMain.lstTimesClick(Sender: TObject);
begin
  if lstTimes.ItemIndex >= 0 then
    dtpTime.Time := EncodeTime(0, Integer(lstTimes.Items.Objects[lstTimes.ItemIndex]) div 60, Integer(lstTimes.Items.Objects[lstTimes.ItemIndex]) mod 60, 0)
  else
    dtpTime.Time := 0;
end;

procedure TFrmMain.lstTimesDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
begin
  with (Control as TJvListBox), (Control as TJvListBox).Canvas do
  begin
    FillRect(Rect);
    cxDrawText(Handle, SecToText(Integer(Items.Objects[Index])), Rect, DT_RIGHT or DT_VCENTER )
  end;
end;

procedure TFrmMain.lstTimesMeasureItem(Control: TWinControl; Index: Integer;
  var Height: Integer);
var
  Rect: TRect;
begin
  with (Control as TJvListBox).Canvas do
  begin
    Font := (Control as TJvListBox).Font;
    Rect := bounds(0, 0, (Control as TJvListBox).Width,  Height);
    cxDrawText(Handle, (Control as TJvListBox).Items[Index], Rect, DT_RIGHT or DT_VCENTER or DT_CALCRECT);
    Height := Rect.Bottom -Rect.Top;
  end;
end;

function TFrmMain.SaveToFile: Boolean;
begin
  result := False;
  with TSaveDialog.Create(Self) do
  try
    DefaultExt := '.tick';
    Filter := _('Tick tick files (*.tick)|*tick|Any file|*.*');
    if Execute then
    try
      lstTimes.Items.SaveToFile(FileName);
      Modified := False;
      result := True;
    except
      MessageDlg(Format(_('Can''not save the filename %s'), [FileName]), mtError, [mbOK], 0);
    end;
  finally
    Free;
  end;
end;

function TFrmMain.SecToText(Value: Integer): string;
begin
  result := Format('%2d:%0.2d', [Value div 60, Value mod 60]);
end;

procedure TFrmMain.SetRemainingTime(const Value: Integer);
var
  Text: string;
begin
  FRemainingTime := Value;
  Text := SecToText(Value);
  while Length(Text) < 5 do
    Text := ' ' +Text;

  labTimer.Text := text;
end;

procedure TFrmMain.tmrMainTimer(Sender: TObject);
begin
  RemainingTime := RemainingTime -1;
  if RemainingTime = 0 then
  begin
    if lstTimes.ItemIndex < lstTimes.Items.Count -1 then
    begin
      PlaySound('sound', hInstance, SND_RESOURCE or SND_SYNC);
      PlaySound('metronome', hInstance, SND_RESOURCE or SND_ASYNC or SND_LOOP);
      lstTimes.ItemIndex := lstTimes.ItemIndex +1;
      RemainingTime := StrToInt(lstTimes.Items[lstTimes.ItemIndex]);
    end
    else
      actStop.Execute;
  end;
end;

end.
